package com.qf.zuoye0620.utils;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;

/**
 * @Author UNIQ7xi
 * @Date 2023/6/20 19:01
 * @Version v1.8
 **/
public class PasswordUtils {
    private static final int SALT_LENGTH = 16;
    private static final String DIGEST_ALGORITHM = "SHA-256";

    /**
     * 对密码进行加盐哈希操作
     */
    public static String hashPassword(String plainPassword) throws NoSuchAlgorithmException {
        byte[] salt = generateSalt();
        byte[] hash = computeHashWithSalt(plainPassword.getBytes(), salt);
        return toHexString(salt) + ":" + toHexString(hash);
    }

    /**
     * 验证密码是否匹配
     */
    public static boolean verifyPassword(String plainPassword, String hashedPassword)
            throws NoSuchAlgorithmException {
        String[] parts = hashedPassword.split(":");
        byte[] salt = fromHexString(parts[0]);
        byte[] expectedHash = fromHexString(parts[1]);
        byte[] actualHash = computeHashWithSalt(plainPassword.getBytes(), salt);
        return MessageDigest.isEqual(expectedHash, actualHash);
    }

    private static byte[] generateSalt() {
        byte[] salt = new byte[SALT_LENGTH];
        new SecureRandom().nextBytes(salt);
        return salt;
    }

    private static byte[] computeHashWithSalt(byte[] input, byte[] salt) throws NoSuchAlgorithmException {
        MessageDigest digest = MessageDigest.getInstance(DIGEST_ALGORITHM);
        digest.reset();
        digest.update(salt);
        return digest.digest(input);
    }

    private static String toHexString(byte[] bytes) {
        StringBuilder builder = new StringBuilder();
        for (byte b : bytes) {
            builder.append(String.format("%02x", b));
        }
        return builder.toString();
    }

    private static byte[] fromHexString(String str) {
        byte[] bytes = new byte[str.length() / 2];
        for (int i = 0; i < bytes.length; i++) {
            bytes[i] = (byte) Integer.parseInt(str.substring(i * 2, i * 2 + 2), 16);
        }
        return bytes;
    }
}
